type t =
    { 
      output_name : string ref;
      distance: string ref;
    }

let output_name flags = !(flags.output_name)
let distance flags = !(flags.distance)

let parse_arguments () =
  let usage_msg = "\
Usage: " ^ Filename.basename Sys.executable_name ^ " "
  in
  let ifaces = ref [] in
  let add_interface name =
    ifaces := name :: !ifaces
  in
  let flags =
    { 
      output_name = ref "o.out";
      distance = ref "Soergel";
    } 
  in
    Arg.parse
      [ "--output-name", Arg.Set_string flags.output_name, "<name> Out file name (default=o.out)";
	"--use-distance-file", Arg.Set_string flags.distance, "<distance> Use Distance file (default=Canberra)"
      ]
      add_interface usage_msg;
    (List.rev !ifaces), flags
      
let rec analize dist = 
  let distance_file = dist ^ ".res" in 
  let lines = ref [] in
  let file = open_in distance_file in  
    try
      while true; do
	let line = input_line file in
	let first = StringAux.between line '(' ',' in
 	let second = StringAux.between line ',' ')' in  
 	let value = StringAux.suffix_from line (String.rindex line ' ') in 
 	  lines := ((first, second), value) :: !lines; 
      done; 
      []
    with End_of_file ->
      close_in file;
      List.rev !lines

let convert_to_string ((f,s),v) = "(" ^ f ^ "," ^ s ^ ")" ^ v 

let pp l = List.iter (fun x -> print_endline (convert_to_string x)) l

let min_dist prg dist = 
  let filter_prg prg dist = 
    List.filter (fun ((fst, snd), value) -> fst = prg || snd = prg ) (analize dist) 
  in
  let filtered = filter_prg prg dist in
  let rec aux l em =
    match l with 
	[] -> em
      | hd :: tl when float_of_string (snd(hd)) < float_of_string (snd(em)) -> 
	  aux tl hd
      | hd :: tl -> aux tl em 
  in 
    pp filtered;
    print_endline ("--> " ^ (convert_to_string (aux (List.tl filtered) (List.hd filtered))));
    aux (List.tl filtered) (List.hd filtered)
let write file_name min_names = 
  let out = open_out file_name in
    List.iter (fun x -> Printf.fprintf out "%s\n" (convert_to_string x)) min_names;
    close_out out

let _ = 
  let names, flags = parse_arguments() in 
  let min_names = List.fold_right (fun x l -> (min_dist x (distance flags)) :: l ) names [] in
    write (output_name flags) min_names
